Token whale
1. 题目
1.1 要求:
This ERC20-compatible token is hard to acquire. There’s a fixed supply of 1,000 tokens, all of which are yours to start with.
Find a way to accumulate at least 1,000,000 tokens to solve this challenge
1.2 源码:
1 | pragma solidity ^0.4.21; |
2. 分析
- 2.1 首先对代码进行解读,慢慢看懂代码
1 | pragma solidity ^0.4.21; |
- 2.2 本题的目标就是
balanceOf[player] >= 1000000
而合约中的代币发行量只有 1000 那么多,显然只通过简单的转账操作是不可能实现的,所以,只能往溢出的方向去思考 - 2.3 而合约中能产生溢出的且涉及到 balanceOf 的只有
_transfer
函数中的balanceOf[msg.sender] -= value;
这个可以产生溢出,生成很多很多代币。 - 2.4 合约中调用此内部函数的方法只有
transfer
和transferFrom
。细看可知transfer
函数中 有require(balanceOf[msg.sender] >= value)
检验,这个检验让这个函数变得安全,因为它和_transfer
函数中的balanceOf[msg.sender] -= value;
的msg.sender 保持一致,无法进行溢出操作 - 2.5
transferFrom
合约中有三个校验
1 | // 检查的是 from 这个地址的代币 |
- 2.6 我们可知,它校验的是from 地址 ,但是
_transfer
合约中操作的是msg.sender
这就有了操作空间,只要别人有钱我们就可以通过校验执行以下的一系列操作 - 值得注意的是方法的形参的 to 不能和当前的合约调用者一致,否则他会被_transfer函数中的小小保护机制给还原回去的,我之前就试过
3. 解题
3.1 给函数填入参数

3.2 首先要通过第一个校验:可以用玩家地址(balanceOf[play] = 1000)作为 from ,这样就可以通过第一个校验了

3.3 to 随便填一个地址就可以,只要不和msg.sender 是同一个地址就行
3.4 要通过第二个校验,就需要
allowance[from][msg.sender] >= value
,所以需要先调用approve
函数,将调用者地址合约切回 玩家地址,spender就是 你等下要使用的msg.sender,然后随便授权,我这里授权一块钱,因为一个很简单溢出就是0 - 1

3.5 调用之后,查看 balanceOf[msg.sender]

3.6 再调用
transfer
函数,从 msg.sender 转 钱 给 玩家player

通过!!!

一段时间之后的二刷
攻击合约
1 | /** |